package rise.message;

import java.util.LinkedList;
import java.util.List;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactoryConfigurationError;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import rise.comunity.Status;
import rise.comunity.User;

public class CommunityStatusNotificaton extends Packet {

	private String receiver;
	private List<User> users;

	private static final String USER_TAG = "user";
	private static final String RECEIVER_ATTRIBUTE = "receiver";
	private static final String USERNAME_ATTRIBUTE = "username";
	private static final String STATUS_ATTRIBUTE = "status";

	public CommunityStatusNotificaton(String receiver, int port,
			List<User> users) {
		super(PacketType.COMMUNITY_STATUS_NOTIFICATION, port, -1, -1);
		this.users = users;
		this.receiver = receiver;
	}

	@Override
	public String toXML() {
		Document doc = null;
		try {
			doc = super.createXMLDocument();
		} catch (ParserConfigurationException e1) {
			e1.printStackTrace();
		}

		Element root = doc.createElement(rootElementTag());
		root.setAttribute(RECEIVER_ATTRIBUTE, receiver);
		doc.appendChild(root);

		Element connectionElement = super.createConnectionElement(doc);
		root.appendChild(connectionElement);

		for (User user : users) {
			Element userElement = this.createUserElement(doc, user
					.getUsername(), user.getStatus(), user.getGPSLocation()
					.getLat(), user.getGPSLocation().getLon());
			root.appendChild(userElement);
		}

		String result = null;
		try {
			result = super.generateString(doc);
		} catch (TransformerFactoryConfigurationError e) {
			e.printStackTrace();
		} catch (TransformerException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return result;
	}

	public static CommunityStatusNotificaton createCommunityStatusNotificaton(
			String xmlString) {
		Document doc = Packet.createXMLDocumentFromString(xmlString);

		NodeList list = doc
				.getElementsByTagName(PacketType.COMMUNITY_STATUS_NOTIFICATION
						.toString());
		Node rootNode = list.item(0);
		NamedNodeMap rootAttributes = rootNode.getAttributes();

		NodeList childList = rootNode.getChildNodes();
		List<User> users = new LinkedList<User>();

		Node connectionNode = childList.item(0);
		NamedNodeMap connectionAttribute = connectionNode.getAttributes();

		for (int i = 1; i < childList.getLength(); i++) {
			Node userNode = childList.item(i);
			NamedNodeMap userAttribute = userNode.getAttributes();
			users.add(new User(userAttribute.getNamedItem(STATUS_ATTRIBUTE)
					.getNodeValue(), userAttribute.getNamedItem(
					USERNAME_ATTRIBUTE).getNodeValue(), Double
					.parseDouble(userAttribute.getNamedItem(
							Packet.LAT_ATTRIBUTE).getNodeValue()), Double
					.parseDouble(userAttribute.getNamedItem(
							Packet.LON_ATTRIBUTE).getNodeValue())));
		}

		return new CommunityStatusNotificaton(rootAttributes.getNamedItem(
				RECEIVER_ATTRIBUTE).getNodeValue(),
				Integer.parseInt(connectionAttribute.getNamedItem(
						Packet.PORT_ATTRIBUTE).getNodeValue()), users);
	}

	private Element createUserElement(Document doc, String username,
			Status status, double lat, double lon) {
		Element userElement = doc
				.createElement(CommunityStatusNotificaton.USER_TAG);
		userElement.setAttribute(CommunityStatusNotificaton.USERNAME_ATTRIBUTE,
				username);
		userElement.setAttribute(CommunityStatusNotificaton.STATUS_ATTRIBUTE,
				status.toString());
		userElement.setAttribute(Packet.LAT_ATTRIBUTE, Double.toString(lat));
		userElement.setAttribute(Packet.LON_ATTRIBUTE, Double.toString(lon));

		return userElement;
	}

	@Override
	String rootElementTag() {
		return PacketType.COMMUNITY_STATUS_NOTIFICATION.toString();
	}

	public List<User> getUsers() {
		return users;
	}

	public String getReceiver() {
		return receiver;
	}
}
